#pragma once

#include "PLObject.h"
#include "PLEdge.h"
#include "PLEnums.h"
#include "PLTriangle.h"
#include <set>
#include <string>
#include <vector>

#include "opencv2\opencv.hpp"

/**
  *	A PLBlob is a single region inside an image corresponding to one or more
  * triangles of a model. Two triangles don't share the same PLBlob, when they
  * just share one vertex in the model.
  */
class PLBlob : public PLObject
{
public:
	PLBlob( void );
	virtual ~PLBlob( void );

	void AddOutlineEdge( PLEdge *edge );
	void AddTriangle( PLTriangle *triangle );
	bool AssignOriginalColorValuesToVertexes( const IplImage *texture,
		const std::vector<double*> &textureCoordinates,
		PLFilteringMode filteringMode = PL_FILTERMODE_NEAREST_NEIGHBOR,
		bool textureCoordsIndicesBeginWithOne = true, bool bottemLeftOrigin = true );
	void CalculateOutlineEdgePaths( void );
	PLuint CalculateOutlineTriangleRing( const PLuint &widthInPixels,
		const PLuint &imageWidth, const PLuint &imageHeight,
		const PLuint &numVertexesInModel,
		std::vector<double*> *textureCoordinates, bool textureCoordsIndicesBeginWithOne = true );
	void CalculateOutlineVertexNormals( const std::vector<double*> &textureCoordinates,
		bool textureCoordsIndicesBeginWithOne = true );
	void DeleteData( void );
	const PLuint &GetID( void ) const;
	void RemoveOutlineEdge( PLEdge *edge );
	PLEdge *GetCorrespondingEdge( PLEdge *edge );
	const std::set<PLEdge*, PLEdge::PLEdgeVIPCompare> &GetOutlineEdgeSet( void ) const;
	const std::vector<PLTriangle*> &GetOutlineTriangleRingVector( void ) const;
	const std::vector<PLTriangle*> &GetTriangleVector( void ) const;
	bool HasOutlineEdge( PLEdge *edge ) const;
	bool HasOutlineVertexIndex( const PLuint &vertexIndex ) const;
	void Merge( const PLBlob &blob );
	void UpdateOutlineVertexesIndexes( void );

	static const PLuint &GetNumBlobs( void );

private:
	/** All the edges of the PLBlob object that are adjacent to regions, that are not part of the PLBlob object */
	std::set<PLEdge*, PLEdge::PLEdgeVIPCompare> mOutlineEdgeSet;
	/** Paths of all borders of the PLBlob object, which are the outline edges and all the holes */
	std::vector<std::vector<PLEdge*>*> mOutlineEdgePaths;
	/** Indices of all the vertices that are part of the PLBlob object */
	std::set<PLuint> mOutlineVertexesIndexes;
	/** Vector of pointers to PLTriange objects that form the PLBlob region */
	std::vector<PLTriangle*> mTriangles;
	/** Vector of pointers to PLTriange objects that form the ring around the PLBlob region */
	std::vector<PLTriangle*> mOutlineTriangleRing;
	/** Unique ID of the PLBlob instance*/
	PLuint mID;
	
	/** Current number of PLBlob instances */
	static PLuint numBlobs;
	/** The ID for the next PLBlob instance. This number is incremented by 1 after every instantiation */
	static PLuint runningIDs;
};